Содержание

  • 1  Описание проекта
    • 1.1  Задача
    • 1.2  Ход исследования
    • 1.3  Описание данных
  • 2  Изучение общей информации
    • 2.1  Задача
    • 2.2  Загрузка данных
    • 2.3  Общая информация о данных
    • 2.4  Выводы
  • 3  Подготовка данных
    • 3.1  Задача
    • 3.2  Смена регистра в названиях столбцов
    • 3.3  Преобразование типов данных
    • 3.4  Обработка пропусков
    • 3.5  Проверка данных на дубликаты
    • 3.6  Проверка данных на аномалии и выбросы
    • 3.7  Определение суммарных продаж
    • 3.8  Выводы
  • 4  Исследовательский анализа данных
    • 4.1  Задача
    • 4.2  Количество игр, выпускавшихся в разные годы
    • 4.3  Динамика изменения объема продаж по различным игровым платформам
    • 4.4  Динамика изменения объема продаж для существующих игровых платформ
    • 4.5  Сравнение объема продаж наиболее перспективных платформ
    • 4.6  Влияние отзывов пользователей и критиков на объем продаж
    • 4.7  Сравнение объема продаж игр различных жанров
    • 4.8  Выводы
  • 5  Портрет типичного пользователя
    • 5.1  Задача
    • 5.2  Сравнение наиболее популярных платформ для каждого региона
    • 5.3  Сравнение наиболее популярных жанров для каждого региона
    • 5.4  Влияние рейтинга ESRB на продажи в отдельном регионе
    • 5.5  Выводы
  • 6  Проверка гипотез
    • 6.1  Задача
    • 6.2  Проверка гипотез по игровым платформам
    • 6.3  Проверка гипотез по пользовательским рейтингам
    • 6.4  Выводы
  • 7  Общий вывод
    • 7.1  Задание
    • 7.2  Вывод по обработке данных:
    • 7.3  Вывод по результатам анализа:

Проект: "Выбор игрового продукта для рекламной компании"¶

Описание проекта¶

Задача¶

Вы работаете в интернет-магазине «Стримчик», который продаёт по всему миру компьютерные игры. Из открытых источников доступны исторические данные о продажах игр, оценки пользователей и экспертов, жанры и платформы (например, Xbox или PlayStation). Вам нужно выявить определяющие успешность игры закономерности. Это позволит сделать ставку на потенциально популярный продукт и спланировать рекламные кампании.

Перед вами данные до 2016 года. Представим, что сейчас декабрь 2016 г., и вы планируете кампанию на 2017-й. Нужно отработать принцип работы с данными. Неважно, прогнозируете ли вы продажи на 2017 год по данным 2016-го или же 2027-й — по данным 2026 года.
В наборе данных попадается аббревиатура ESRB (Entertainment Software Rating Board) — это ассоциация, определяющая возрастной рейтинг компьютерных игр. ESRB оценивает игровой контент и присваивает ему подходящую возрастную категорию, например, «Для взрослых», «Для детей младшего возраста» или «Для подростков».

Ход исследования¶

  1. Изучение общей информации
  2. Подготовка данных
  3. Проведение исследовательского анализа данных
  4. Составление портрета типичного пользователя
  5. Проверка гипотез
  6. Составление общего вывода

Описание данных¶

  • Name — название игры
  • Platform — платформа
  • Year_of_Release — год выпуска
  • Genre — жанр игры
  • NA_sales — продажи в Северной Америке (миллионы проданных копий)
  • EU_sales — продажи в Европе (миллионы проданных копий)
  • JP_sales — продажи в Японии (миллионы проданных копий)
  • Other_sales — продажи в других странах (миллионы проданных копий)
  • Critic_Score — оценка критиков (максимум 100)
  • User_Score — оценка пользователей (максимум 10)
  • Rating — рейтинг от организации ESRB (англ. Entertainment Software Rating Board). Эта ассоциация определяет рейтинг компьютерных игр и присваивает им подходящую возрастную категорию.

Данные за 2016 год могут быть неполными.

Изучение общей информации¶

Задача¶

Открыть файл с данными и изучить общую информацию.

Загрузка данных¶

In [1]:
# импорт библиотек
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
from scipy import stats as st

# белая тема plotly
pio.templates.default = 'plotly_white'
# увеличение числа видимых столбцов в таблице
pd.set_option("display.max_columns", 100)
In [2]:
# чтение файла данных в датафрейм из папки по умолчанию и из рабочей директории
try:
    df = pd.read_csv('/datasets/games.csv', sep=',')
except:
    df = pd.read_csv('games.csv', sep=',')

Общая информация о данных¶

In [3]:
# получение первых 10 строк таблицы df
df.head(10)
Out[3]:
Name Platform Year_of_Release Genre NA_sales EU_sales JP_sales Other_sales Critic_Score User_Score Rating
0 Wii Sports Wii 2006.0 Sports 41.36 28.96 3.77 8.45 76.0 8 E
1 Super Mario Bros. NES 1985.0 Platform 29.08 3.58 6.81 0.77 NaN NaN NaN
2 Mario Kart Wii Wii 2008.0 Racing 15.68 12.76 3.79 3.29 82.0 8.3 E
3 Wii Sports Resort Wii 2009.0 Sports 15.61 10.93 3.28 2.95 80.0 8 E
4 Pokemon Red/Pokemon Blue GB 1996.0 Role-Playing 11.27 8.89 10.22 1.00 NaN NaN NaN
5 Tetris GB 1989.0 Puzzle 23.20 2.26 4.22 0.58 NaN NaN NaN
6 New Super Mario Bros. DS 2006.0 Platform 11.28 9.14 6.50 2.88 89.0 8.5 E
7 Wii Play Wii 2006.0 Misc 13.96 9.18 2.93 2.84 58.0 6.6 E
8 New Super Mario Bros. Wii Wii 2009.0 Platform 14.44 6.94 4.70 2.24 87.0 8.4 E
9 Duck Hunt NES 1984.0 Shooter 26.93 0.63 0.28 0.47 NaN NaN NaN
In [4]:
# получение общей информации о данных в таблице df
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 16715 entries, 0 to 16714
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   Name             16713 non-null  object 
 1   Platform         16715 non-null  object 
 2   Year_of_Release  16446 non-null  float64
 3   Genre            16713 non-null  object 
 4   NA_sales         16715 non-null  float64
 5   EU_sales         16715 non-null  float64
 6   JP_sales         16715 non-null  float64
 7   Other_sales      16715 non-null  float64
 8   Critic_Score     8137 non-null   float64
 9   User_Score       10014 non-null  object 
 10  Rating           9949 non-null   object 
dtypes: float64(6), object(5)
memory usage: 1.4+ MB

Выводы¶

В каждой строке таблицы — данные об конкретной компьютерной игре. Часть колонок описывает саму игру: название, игровая платформа, жанр, год релиза. Другая сообщает о продажах в различных в различных регионах мира. Наконец, последняя указывает рейтинги игры в профессиональном сообществе и среди игроков.
Предварительно можно утверждать, что данных достаточно для проверки гипотез. Но встречаются пропуски в данных, а в названиях колонок — расхождения с хорошим стилем. Часть столбцов требует смены типа данных.
Чтобы двигаться дальше, нужно устранить проблемы в данных, в частности, проверить их на выбросы, аномалии, наличие явных дубликатов.

Подготовка данных¶

Задача¶

Подготовить данные:

  • Привести названия столбцов к нижнему регистру;
  • Преобразовать данные в нужные типы;
  • Обработать пропуски;
  • Посчитать суммарные продажи во всех регионах и записать их в отдельный столбец.

Смена регистра в названиях столбцов¶

In [90]:
# приведение к нижнему регистру названий столбцов
df.set_axis(df.columns.str.lower(), axis='columns', copy=False)
df.columns
Out[90]:
Index(['name', 'platform', 'year_of_release', 'genre', 'na_sales', 'eu_sales',
       'jp_sales', 'other_sales', 'critic_score', 'user_score', 'rating',
       'total_sales'],
      dtype='object')

Преобразование типов данных¶

В смене типов данных нуждаются два столбца year_of_release и user_score. Год релиза игры был воспринят как число. Посмотрим, почему то же самое не произошло с оценкой пользователей.

In [6]:
# поиск строковых значений в столбце user_score
score_uniques = df.user_score.unique()
non_float = []
for item in score_uniques:
    try:
        float(item)
    except:
        non_float.append(item)
non_float    
Out[6]:
['tbd']

В столбце user_score (оценка пользователей) встречается значение tbd. Аббревиатура «tbd»" расшифровывается как «To Be Determined», то есть «Будет определено». Используется когда разработчик той или иной игры уже сообщил о том, что она готовится к выходу, но пока еще не может назвать точную дату. Также используется при выходе новых аддонов. Так или иначе значение tbd означает, что пользовательская оценка для игры не определена.

Применяемые преобразования типов:

  • Преобразование данных столбца year_of_release в формат даты отложим до момента, пока не будут обработаны пропуски.
  • Для столбца user_score меняем тип на числовой, при этом значение tbd преобразуется в NaN.
In [7]:
# преобразование типа в столбце year_of_release с заменой значений tbd на NaN
df['user_score'] = pd.to_numeric(df['user_score'], errors='coerce')

Обработка пропусков¶

In [8]:
# количество отсутствующих значений в столбцах
df.isnull().sum()
Out[8]:
name                  2
platform              0
year_of_release     269
genre                 2
na_sales              0
eu_sales              0
jp_sales              0
other_sales           0
critic_score       8578
user_score         9125
rating             6766
dtype: int64

Наибольшее количество пропусков находится в столбцах с рейтингами. Отсутствие значений в столбцах critic_score и user_scoreмало о чем говорит. Посмотрим на уникальные значения в столбце rating.

In [9]:
# просмотр уникальных значений столбца rating
df.rating.unique()
Out[9]:
array(['E', nan, 'M', 'T', 'E10+', 'K-A', 'AO', 'EC', 'RP'], dtype=object)

Расшифровка категорий рейтинга ESRB:

  • «EC» («Early childhood») — «Для детей младшего возраста»
  • «E» («Everyone») — «Для всех» (ранее «K-A»)
  • «E10+» («Everyone 10 and older») — «Для всех от 10 лет и старше»
  • «T» («Teen») — «Подросткам»
  • «M» («Mature») — «Для взрослых»
  • «AO» («Adults Only 18+») — «Только для взрослых»
  • «RP» («Rating Pending») — «Рейтинг ожидается»

Среди значений столбца rating встречается категория RP. Ее можно воспринимать как отсутствие рейтинга и именно ею и заменить отсутствующие значения.

Применяемые преобразования:

  • Удаляем строки с NaN в столбцах name и year_of_release, так как их немного.
  • Для столбца year_of_release меняем тип на целочисленный, так располагаем не датой. а только годом релиза.
  • Для столбца user_scor меняем тип на числовой, при этом значение tbd преобразуется в NaN.
  • В столбце rating значение NaN меняем на RP - категория с неизвестным рейтингом.
In [10]:
# удаление пропусков
df.dropna(subset=['name', 'year_of_release'], inplace=True)
# смена типа в столбце year_of_release
df['year_of_release'] = df['year_of_release'].astype('int64')
# замена пропусков в столбце rating
df['rating'].fillna('RP', inplace=True)
In [11]:
# проверка смены типов данных
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 16444 entries, 0 to 16714
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   name             16444 non-null  object 
 1   platform         16444 non-null  object 
 2   year_of_release  16444 non-null  int64  
 3   genre            16444 non-null  object 
 4   na_sales         16444 non-null  float64
 5   eu_sales         16444 non-null  float64
 6   jp_sales         16444 non-null  float64
 7   other_sales      16444 non-null  float64
 8   critic_score     7983 non-null   float64
 9   user_score       7463 non-null   float64
 10  rating           16444 non-null  object 
dtypes: float64(6), int64(1), object(4)
memory usage: 1.5+ MB
In [12]:
# оценка количества отсутствующих значений
df.isnull().sum()
Out[12]:
name                  0
platform              0
year_of_release       0
genre                 0
na_sales              0
eu_sales              0
jp_sales              0
other_sales           0
critic_score       8461
user_score         8981
rating                0
dtype: int64

Проверка данных на дубликаты¶

Проведем проверку на явные дубликаты строк, а также неявные дубликаты в значениях категориальных признаков: name, genre и platform.

In [13]:
# проверка на явные дубликаты в строках
print('Число дубликатов:', df.duplicated().sum())
Число дубликатов: 0
In [14]:
# поиск повторяющихся значений в столбце name
df['name'].value_counts()
Out[14]:
Need for Speed: Most Wanted               12
LEGO Marvel Super Heroes                   9
Ratatouille                                9
FIFA 14                                    9
Terraria                                   8
                                          ..
Loving Life with Hello Kitty & Friends     1
Scrabble (Others sales)                    1
Viva Pinata: Party Animals                 1
Sands of Destruction                       1
Haitaka no Psychedelica                    1
Name: name, Length: 11426, dtype: int64
In [15]:
# проверка уникальности одного из названий
df[df['name'] == 'Need for Speed: Most Wanted']
Out[15]:
name platform year_of_release genre na_sales eu_sales jp_sales other_sales critic_score user_score rating
253 Need for Speed: Most Wanted PS2 2005 Racing 2.03 1.79 0.08 0.47 82.0 9.1 T
523 Need for Speed: Most Wanted PS3 2012 Racing 0.71 1.46 0.06 0.58 NaN NaN RP
1190 Need for Speed: Most Wanted X360 2012 Racing 0.62 0.78 0.01 0.15 83.0 8.5 T
1591 Need for Speed: Most Wanted X360 2005 Racing 1.00 0.13 0.02 0.10 83.0 8.5 T
1998 Need for Speed: Most Wanted XB 2005 Racing 0.53 0.46 0.00 0.05 83.0 8.8 T
2048 Need for Speed: Most Wanted PSV 2012 Racing 0.33 0.45 0.01 0.22 NaN NaN RP
3581 Need for Speed: Most Wanted GC 2005 Racing 0.43 0.11 0.00 0.02 80.0 9.1 T
5972 Need for Speed: Most Wanted PC 2005 Racing 0.02 0.23 0.00 0.04 82.0 8.5 T
6273 Need for Speed: Most Wanted WiiU 2013 Racing 0.13 0.12 0.00 0.02 NaN NaN RP
6410 Need for Speed: Most Wanted DS 2005 Racing 0.24 0.01 0.00 0.02 45.0 6.1 E
6473 Need for Speed: Most Wanted GBA 2005 Racing 0.19 0.07 0.00 0.00 NaN 8.3 E
11715 Need for Speed: Most Wanted PC 2012 Racing 0.00 0.06 0.00 0.02 82.0 8.5 T

Среди названий игр встречаются повторные, но они отличаются по другим характеристикам - игровой платформой или годом выпуска.
Проверим категориальные признаки genre и platform и чуть ближе познакомимся с жанрами и игровыми платформами.

In [16]:
# просмотр уникальных значений столбца genre
df.genre.unique()
Out[16]:
array(['Sports', 'Platform', 'Racing', 'Role-Playing', 'Puzzle', 'Misc',
       'Shooter', 'Simulation', 'Action', 'Fighting', 'Adventure',
       'Strategy'], dtype=object)
In [17]:
# просмотр уникальных значений столбца platform
df.platform.unique()
Out[17]:
array(['Wii', 'NES', 'GB', 'DS', 'X360', 'PS3', 'PS2', 'SNES', 'GBA',
       'PS4', '3DS', 'N64', 'PS', 'XB', 'PC', '2600', 'PSP', 'XOne',
       'WiiU', 'GC', 'GEN', 'DC', 'PSV', 'SAT', 'SCD', 'WS', 'NG', 'TG16',
       '3DO', 'GG', 'PCFX'], dtype=object)

Данные охватывают несколько поколений популярных игровых приставок, выпускавшихся с 1980 по 2016 год.
Список производителей и названия игровых приставок:

  • Atari:
    • «2600»(Atari 2600);
  • Bandai:
    • «WS»(WonderSwan Color);
  • Microsoft:
    • «XB»(Xbox), «X360»(Xbox 360), «XOne»(Xbox One);
  • NEC:
    • «PCFX»(PC-FX), «PC»(PC Engine), «TG16»(TurboGrafx-16);
  • Nintendo:
    • «Wii»(Wii), «WiiU»(Wii U), «DS»(Nintendo DS), «NES»(Nintendo Entertainment System), «SNES»(Super Nintendo Entertainment System), «GB»(Gameboy Player), «GBA»(Game Boy Advance), «3DS»(Nintendo 3DS), «GC»(Nintendo GameCube), «N64»(Nintendo 64);
  • Panasonic:
    • «3DO»(3DO);
  • Sega:
    • «GEN»(Sega Genesis), «GG»(Sega Game Gear), «SCD»(Sega CD), «SAT»(SEGA Saturn), «DC»(Dreamcast);
  • SNK:
    • «NG»(Neo-Geo);
  • Sony:
    • «PS»(PlayStation),«PS2»(PlayStation 2), «PS3»(PlayStation 3), «PS4»(PlayStation 4), «PSV»(PlayStation Vita), PSP»(PlayStation Portable);

В данных не дубликатов обнаружилось.

Проверка данных на аномалии и выбросы¶

Ранее мы уже просмотрели уникальные значения в категориальных признаках и там аномалии не обнаружились. Изучим числовые признаки. И для начала взглянем на признаки с дискретными значениями - year_of_release, user_score, critic_score.

In [18]:
# признаки с дискретными значениями
df['year_of_release'].unique()
Out[18]:
array([2006, 1985, 2008, 2009, 1996, 1989, 1984, 2005, 1999, 2007, 2010,
       2013, 2004, 1990, 1988, 2002, 2001, 2011, 1998, 2015, 2012, 2014,
       1992, 1997, 1993, 1994, 1982, 2016, 2003, 1986, 2000, 1995, 1991,
       1981, 1987, 1980, 1983], dtype=int64)
In [19]:
df['user_score'].unique()
Out[19]:
array([8. , nan, 8.3, 8.5, 6.6, 8.4, 8.6, 7.7, 6.3, 7.4, 8.2, 9. , 7.9,
       8.1, 8.7, 7.1, 3.4, 5.3, 4.8, 3.2, 8.9, 6.4, 7.8, 7.5, 2.6, 7.2,
       9.2, 7. , 7.3, 4.3, 7.6, 5.7, 5. , 9.1, 6.5, 8.8, 6.9, 9.4, 6.8,
       6.1, 6.7, 5.4, 4. , 4.9, 4.5, 9.3, 6.2, 4.2, 6. , 3.7, 4.1, 5.8,
       5.6, 5.5, 4.4, 4.6, 5.9, 3.9, 3.1, 2.9, 5.2, 3.3, 4.7, 5.1, 3.5,
       2.5, 1.9, 3. , 2.7, 2.2, 2. , 9.5, 2.1, 3.6, 2.8, 1.8, 3.8, 0. ,
       1.6, 9.6, 2.4, 1.7, 1.1, 0.3, 1.5, 0.7, 1.2, 2.3, 0.5, 1.3, 0.2,
       0.6, 1.4, 0.9, 1. , 9.7])
In [20]:
df['critic_score'].unique()
Out[20]:
array([76., nan, 82., 80., 89., 58., 87., 91., 61., 97., 95., 77., 88.,
       83., 94., 93., 85., 86., 98., 96., 90., 84., 73., 74., 78., 92.,
       71., 72., 68., 62., 49., 67., 81., 66., 56., 79., 70., 59., 64.,
       75., 60., 63., 69., 50., 25., 42., 44., 55., 48., 57., 29., 47.,
       65., 54., 20., 53., 37., 38., 33., 52., 30., 32., 43., 45., 51.,
       40., 46., 39., 34., 41., 36., 31., 27., 35., 26., 19., 28., 23.,
       24., 21., 17., 13.])

В столбцах year_of_release, user_score, critic_score аномалий не оказалось. Посмотрим данные в столбцах продаж - na_sales, eu_sales, jp_sales, other_sales. Сначала убедимся, что там нет отрицательных значений (это послужит косвенным признаком достоверности данных). Затем удалим строки, где суммы продаж во всех колонках равны нулю. После построим графики boxplot для этих признаков.

In [21]:
# выбор строк, где хотя бы один из признаков отрицательный
print('Число строк с отрицательными продажами:', 
      df[(df['na_sales'] < 0) | (df['eu_sales'] < 0) | (df['jp_sales'] < 0) | (df['other_sales'] < 0)]['name'].sum()
     )
Число строк с отрицательными продажами: 0
In [22]:
# удаление строк с отсутствием продаж
df = df[(df['na_sales'] > 0) | (df['eu_sales'] > 0) | (df['jp_sales'] > 0) | (df['other_sales'] > 0)]
In [23]:
# график оценки выбросов
fig = px.box(df[['na_sales', 'eu_sales', 'jp_sales', 'other_sales']],
             title='График оценки выбросов <br>в распределениях продаж до очистки')
fig.update_xaxes(title_text='Регион продаж')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()
In [24]:
# функция обрезки выбросов
def cut_outliers(dt, cols):
    for col in cols:
        if dt[col].dtypes == 'int64' or dt[col].dtypes == 'float64':
            pass# расчет процентилей
            quantiles = dt[col].quantile(q=[.001, .99])
            dt[col]  = dt.loc[(dt[col] >= quantiles.iloc[0]) & (dt[col] <= quantiles.iloc[1]), col].copy()
    return
In [25]:
# обрезка выбросов для выбранных признаков
to_cut = ['na_sales', 'eu_sales', 'jp_sales', 'other_sales']
cut_outliers(df, to_cut)
In [26]:
# график проверки выбросов
fig = px.box(df[['na_sales', 'eu_sales', 'jp_sales', 'other_sales']],
             title='График оценки выбросов <br>в распределениях продаж после очистки')
fig.update_xaxes(title_text='Регион продаж')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()
In [27]:
# удаление строк с пустыми значениями продаж
df = df[(df['na_sales'].notna()) | (df['eu_sales'].notna()) | (df['jp_sales'].notna()) | (df['other_sales'].notna())]
print('Размер датасета после удаления выбросов:', df.shape)
Размер датасета после удаления выбросов: (16416, 11)

Определение суммарных продаж¶

In [28]:
# создание столбца с общим объемом продаж total_sales
df['total_sales'] = df.filter(like='_sales').sum(axis=1)
df.head()
Out[28]:
name platform year_of_release genre na_sales eu_sales jp_sales other_sales critic_score user_score rating total_sales
5 Tetris GB 1989 Puzzle NaN NaN NaN 0.58 NaN NaN RP 0.58
9 Duck Hunt NES 1984 Shooter NaN 0.63 0.28 0.47 NaN NaN RP 1.38
14 Kinect Adventures! X360 2010 Misc NaN NaN 0.24 NaN 61.0 6.3 E 0.24
16 Grand Theft Auto V PS3 2013 Action NaN NaN 0.98 NaN 97.0 8.2 M 0.98
17 Grand Theft Auto: San Andreas PS2 2004 Action NaN 0.40 0.41 NaN 95.0 9.0 M 0.81

Выводы¶

На этапе подготовки данных была проведена замена типов данных для столбцов year_of_release и user_score. Были удалены немногочленные пропуски в столбцах name, platform, year_of_release и обработаны пропуски в столбце rating. Данные были проверены на наличие явных и неявных дубликатов, а также аномалий в данных. Были удалены сильные выбросы в данных об объемах продаж. Добавлен столбец суммарных продаж total_sales.

В датасете отсутствуют данные о рейтингах для половины игр. Если заменить их средними значениями - это внесет искажение при их анализе, а при удалении потеряются данные по продажам. Однако, в данном проекте исследования ведутся по срезам отдельных столбцов, все они одновременно не нужны. Раз так, пока NaN в датасете можно оставить.

Исследовательский анализа данных¶

Задача¶

Провести исследовательский анализ данных:

  • Посмотреть, сколько игр выпускалось в разные годы;
  • Посмотреть, как менялись продажи по платформам. Выбрать платформы с наибольшими суммарными продажами и построить распределение по годам;
  • Определить, за какой характерный срок появляются новые и исчезают старые платформы. Выделить актуальный период;
  • Выбрать несколько потенциально прибыльных платформ.
  • Построить график «ящик с усами» по глобальным продажам игр в разбивке по платформам;
  • Посмотреть, как влияют на продажи внутри одной популярной платформы отзывы пользователей и критиков. Построить диаграмму рассеяния и посчитать корреляцию между отзывами и продажами;
  • Посмотреть на общее распределение игр по жанрам. Выявить наиболее прибыльные жанры;

Количество игр, выпускавшихся в разные годы¶

In [29]:
# диаграмма выпуска игр в разные годы
fig = px.area(df.groupby('year_of_release')['name'].count(), 
             title='Годовой объем выпуска игр в разные годы')
fig.update_xaxes(title_text='Год выпуска')
fig.update_yaxes(title_text='Кол-во игр, ед.')
fig.update_layout(showlegend=False)
fig.show()

До 1994 кол-во выпускаемых игр составляло менее 100 шт./год. За первые 10 лет всего было выпущено около 200 игр. Так что период с 1980 до 1995 года не представляет особой важности.

Динамика изменения объема продаж по различным игровым платформам¶

In [30]:
# создание датафрейма с индексом и столбцом platform
platform_games = df.pivot_table(index='platform', values='total_sales', aggfunc=['count'])
platform_games = platform_games['count']['total_sales'].reset_index()
platform_games.set_index(keys=platform_games.platform, inplace=True)
# диаграмма выпуска игр для различных платформ
fig = px.bar(platform_games.sort_values(by='total_sales', ascending=True),
             orientation='h',
             color='platform',
             title='Число выпущенных игр для разных игровых платформ')
fig.update_xaxes(title_text='Кол-во игр, ед.')
fig.update_yaxes(title_text='Игровая платформа')
fig.show()
In [31]:
# топ-5 платформ по продажам
top_sales5 = df.groupby('platform')['total_sales'].count().sort_values(ascending=False).head(5).index
print('Топ-5 платформ по продажам:', list(top_sales5))
Топ-5 платформ по продажам: ['PS2', 'DS', 'PS3', 'Wii', 'X360']
In [32]:
# динамика продаж топ-5 игровых платформ
fig = px.line(df.query('platform in @top_sales5 & year_of_release >= 2000')
             .pivot_table(index='year_of_release', columns='platform', values='total_sales', aggfunc='sum', fill_value=0), 
             title='Динамика продаж топ-5 игровых платформ')
fig.update_xaxes(title_text='Год выпуска')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()

Определение списка популярных прежде платформ:

  • Сначала отберем 10 самых популярных платформ.
  • Составим для них сводную таблицы продаж по годам за полный общий период.
  • Составим на основании ее список платформ с нулевыми продажами в 2016-ом году.
In [33]:
# топ-10 платформ по продажам
top_sales10 = df.groupby('platform')['total_sales'].count().sort_values(ascending=False).head(10).index
top10_platform_years_sales = (
    df.query('platform in @top_sales10')
    .pivot_table(index='platform', columns='year_of_release', values='total_sales', aggfunc='sum', fill_value=0)
)
# топ устаревших платформ
old_top = top10_platform_years_sales[top10_platform_years_sales[2016] == 0].index
print('Топ устаревших платформ:', list(old_top))
Топ устаревших платформ: ['DS', 'GBA', 'PS', 'PS2', 'PSP', 'XB']

Определение периода жизни платформ:

  • Год выпуска платформы определяем как первый год с ненулевыми продажами.
  • Определим последний год с ненулевыми продажами.
  • Так как период жизни платформы можно определить лишь после ее закрытия, выделим те платформы, чей последний ненулевой год был ранее 2016-го года.
  • Возьмем разницу между годом закрытия и годом выпуска этих платформ.
  • Предполагая, что выпуск платформы происходил в начале года, а закрытие - в конце, добавляем к периоду 1 целый год.
  • Возьмем среднее по ним, а так как неполный год уже был учтен, округлим получившееся значение в меньшую сторону.
In [34]:
# первый и последний годы жизни игровой платформы
platform_years = df.query('total_sales > 0').groupby('platform')['year_of_release'].agg([min, max])
# список устаревших платформ
old_platforms = platform_years[platform_years['max'] < 2016].index
# срок жизни игровых платформ
old_platforms_dur = platform_years['max'][old_platforms] - platform_years['min'][old_platforms] + 1
print('Характерный период жизни платформы:', np.floor(old_platforms_dur.mean()))
Характерный период жизни платформы: 8.0

Для дальнейшего анализа оставим только игровые платформы с ненулевым объемом продаж в 2016 году, а глубину истории для первоначальной оценки ограничим последними 8-ю годами - c 2008 по 2016 годы.

Динамика изменения объема продаж для существующих игровых платформ¶

In [35]:
# список актуальных платформ
new_platforms = platform_years[platform_years['max'] == 2016].index
print('Актуальные в 2016-ом году платформы:', list(new_platforms))
Актуальные в 2016-ом году платформы: ['3DS', 'PC', 'PS3', 'PS4', 'PSV', 'Wii', 'WiiU', 'X360', 'XOne']
In [36]:
# актуальный датасет
new_df = df.query('platform in @new_platforms & year_of_release >= 2008').copy()
new_df
Out[36]:
name platform year_of_release genre na_sales eu_sales jp_sales other_sales critic_score user_score rating total_sales
14 Kinect Adventures! X360 2010 Misc NaN NaN 0.24 NaN 61.0 6.3 E 0.24
16 Grand Theft Auto V PS3 2013 Action NaN NaN 0.98 NaN 97.0 8.2 M 0.98
23 Grand Theft Auto V X360 2013 Action NaN NaN 0.06 NaN 97.0 8.1 M 0.06
29 Call of Duty: Modern Warfare 3 X360 2011 Shooter NaN NaN 0.13 NaN 88.0 3.4 M 0.13
31 Call of Duty: Black Ops 3 PS4 2015 Shooter NaN NaN 0.36 NaN NaN NaN RP 0.36
... ... ... ... ... ... ... ... ... ... ... ... ...
16705 15 Days PC 2009 Adventure 0.0 0.01 0.00 0.0 63.0 5.8 RP 0.01
16707 Aiyoku no Eustia PSV 2014 Misc 0.0 0.00 0.01 0.0 NaN NaN RP 0.01
16710 Samurai Warriors: Sanada Maru PS3 2016 Action 0.0 0.00 0.01 0.0 NaN NaN RP 0.01
16712 Haitaka no Psychedelica PSV 2016 Adventure 0.0 0.00 0.01 0.0 NaN NaN RP 0.01
16714 Winning Post 8 2016 PSV 2016 Simulation 0.0 0.00 0.01 0.0 NaN NaN RP 0.01

5623 rows × 12 columns

In [37]:
# динамика продаж существующих игровых платформ
fig = px.line(new_df.pivot_table(index='year_of_release', columns='platform', values='total_sales', aggfunc='sum', fill_value=0), 
             title='Динамика продаж существующих игровых платформ')
fig.update_xaxes(title_text='Год выпуска')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()

Определим наиболее перспективные платформы на основании роста за последние несколько лет. Если характерный период жизни платформы составляет 8 лет, можно предположить, что в первые 4 года от этого срока популярность платформы растет, во вторые 4 - падает. Убедимся в этом.

Определение периода роста:

  • Начало периода роста продаж по каждой платформе определяем как первый год с ненулевыми продажами.
  • Его завершение зафиксируем как снижение 3-х периодного скользящего среднего MA(3) в течении двух лет.
  • Вычтем эти два года из полученного значения.
  • С учетом последнего года мы получим начала спада, без учета - конец роста.
  • Период роста продаж для платформы получим как разницу между началом продаж и годом оканчания роста продаж.
  • Наконец, возьмем среднее по всем значениям и округлим его в меньшую сторону.

В выборку не будут включены платформы в стадии роста продаж и те, чей срок жизни составил менее 1-2 года.

In [38]:
# таблица суммарных продаж по платформам в разные годы
platform_sales = df.pivot_table(index='platform', columns='year_of_release', values='total_sales', aggfunc='sum').copy()
platform_sales.fillna(0, inplace=True)
In [39]:
# функция проверки разрывов в данных
def start_checking(data, row, col, num):
    counter = 0
    for i in range(num):
        if data.iloc[row, col-i] > 0:
            counter += 1
    return counter == num

# функция расчета скользящего среднего
def ma(data, row, col, period):
    values = [data.iloc[row, col-n] for n in range(period) if col >= (period - 1)]
    return sum(values) / period    
In [40]:
ma_period = 3
platform_interval = {}
# цикл по индексам пивот-таблицы platform_sales
for i in range(platform_sales.shape[0]):
    flag_start = False
    start = 0
    # счетчик убыточных лет
    counter = 0
    # итерируемся со сдвигом значения вперед для фиксации отсутствия данных
    for j in range(ma_period-1, platform_sales.shape[1]):
        # начало продаж
        if start_checking(platform_sales, i, j, ma_period) and flag_start == False:
            flag_start = True
            start = (j - (ma_period-1))
            j = 0
    # итерируемся со сдвигом значения вперед для сравнения с предыдущим
    for j in range(start, platform_sales.shape[1]):
        # фиксация спада продаж
        if flag_start == True:
            if  counter < 2: 
                # сравниваем скользящие средние
                if ma(platform_sales, i, j, ma_period) < ma(platform_sales, i, j-1, ma_period):
                    counter += 1
                else:
                    counter = 0
                    pass
            # запись длины периода
            elif counter == 2:                
                platform_interval[platform_sales.index[i]] = (j - 2) - start
                break
            else:
                pass
In [41]:
# конвертирум словарь с периодами в датафрейм
platform_interval = pd.DataFrame.from_dict(platform_interval, orient='index')
# добавим в датафрейм индекс с названиями платформ
intervals = platform_interval.copy().reset_index()
intervals.set_index(keys=platform_interval.index, inplace=True)
intervals = intervals.set_axis(['platform', 'interval'], axis=1)
In [42]:
# график периодов роста продаж для различных платформ
fig = px.bar(intervals,
             orientation='h',
             color='platform',
             title='Зафиксированный период роста продаж игр <br>для различных платформ')
fig.update_xaxes(title_text='Кол-во лет, ед.')
fig.update_yaxes(title_text='Игровая платформа')
fig.show()
In [43]:
print(f'Средний период роста продаж составляет: {round(intervals["interval"].mean(), 2)} года')
Средний период роста продаж составляет: 4.64 года

Наше первоначальное о предположение о том, что полный период роста продаж для платформ составляет 4 года подтвердилось. Можно также выделить период вероятного продолжения роста после его начала. Очевидно, что для фиксации тенденции к росту нужно минимум два годовых значения. Таким образом, период актуальности платформы окажется равным 2 годам.

Сравнение объема продаж наиболее перспективных платформ¶

Дальнейший отбор платформ будем делать исходя из следующих критериев:

  • соблюдение пределов среднего периода роста продаж;
  • подтверждение роста продаж с опорой на данный период;
  • отсутствие признаков падения объема продаж;
  • высокий уровень объема продаж в актуальный период.
In [44]:
# коррекция датасета
new_df = new_df.query('platform in @new_platforms & year_of_release >= 2015')
new_df
Out[44]:
name platform year_of_release genre na_sales eu_sales jp_sales other_sales critic_score user_score rating total_sales
31 Call of Duty: Black Ops 3 PS4 2015 Shooter NaN NaN 0.36 NaN NaN NaN RP 0.36
77 FIFA 16 PS4 2015 Sports 1.12 NaN 0.06 NaN 82.0 4.3 E 1.18
87 Star Wars Battlefront (2015) PS4 2015 Shooter NaN NaN 0.22 NaN NaN NaN RP 0.22
94 FIFA 17 PS4 2016 Sports 0.66 NaN 0.08 NaN 85.0 5.0 E 0.74
99 Call of Duty: Black Ops 3 XOne 2015 Shooter NaN NaN 0.01 NaN NaN NaN RP 0.01
... ... ... ... ... ... ... ... ... ... ... ... ...
16699 The Longest 5 Minutes PSV 2016 Action 0.00 0.0 0.01 0.0 NaN NaN RP 0.01
16703 Strawberry Nauts PSV 2016 Adventure 0.00 0.0 0.01 0.0 NaN NaN RP 0.01
16710 Samurai Warriors: Sanada Maru PS3 2016 Action 0.00 0.0 0.01 0.0 NaN NaN RP 0.01
16712 Haitaka no Psychedelica PSV 2016 Adventure 0.00 0.0 0.01 0.0 NaN NaN RP 0.01
16714 Winning Post 8 2016 PSV 2016 Simulation 0.00 0.0 0.01 0.0 NaN NaN RP 0.01

1105 rows × 12 columns

In [45]:
# динамика продаж актуальных платформ
actual_sales = new_df.pivot_table(index='year_of_release',
                                  columns='platform',
                                  values='total_sales',
                                  aggfunc='sum',
                                  fill_value=0
                                 )
actual_sales
Out[45]:
platform 3DS PC PS3 PS4 PSV Wii WiiU X360 XOne
year_of_release
2015 21.30 8.52 16.82 79.50 6.25 1.14 14.89 11.96 50.64
2016 8.57 5.25 3.60 54.18 4.25 0.18 4.60 1.52 24.10

Среди существующих платформ выделим топ-5, а также наиболее перспективные платформы.

In [46]:
# топ-5 существующих платформ по общим продажам
top5_platforms = (actual_sales.sum()
        .sort_values(ascending=False)
        .head(5)
        .copy()
        .reset_index()
       )
# добавим в датафрейм индекс с названиями платформ
top5_platforms.set_index(keys=top5_platforms['platform'], inplace=True)
top5_platforms_list = list(top5_platforms['platform'])
print('Список топ-5 существующих платформ по общим продажам в 2015-2016 гг.:', top5_platforms_list)
Список топ-5 существующих платформ по общим продажам в 2015-2016 гг.: ['PS4', 'XOne', '3DS', 'PS3', 'WiiU']
In [47]:
fig = px.bar(top5_platforms,
             color='platform',
             title='Топ-5 существующих платформ <br>по общим продажам в 2015-2016 гг.')
fig.update_xaxes(title_text='Объем продаж, млн. долл.')
fig.update_yaxes(title_text='Игровая платформа')
fig.show()
In [48]:
# сводная таблица по продажам 2014-2016 гг.
sales_14_16 = (
    df.query('platform in @new_platforms & year_of_release >= 2012')
    .pivot_table(index='year_of_release',
                 columns='platform',
                 values='total_sales',
                 aggfunc='sum',
                 fill_value=0)
)
# проверка раста продаж для платформ
ascend_query = list(sales_14_16.loc[2012] < sales_14_16.loc[2016])
# перспективные платформы
prospect_platforms = \
new_df.pivot_table(index='platform',
                   columns='year_of_release',
                   values='total_sales',
                   aggfunc='sum', fill_value=0
)[ascend_query].index
print('Перспективные платформы:', list(prospect_platforms))
Перспективные платформы: ['PS4', 'XOne']

Уточним список перспективных платформ с помощью критериев, которые были указаны чуть раньше.

  1. Мы уже определили средний период роста в 4 года. С опорой на него в разряд перспективными можно зачислить лишь платформы, выпущенные не позднее 2012 года. Таких две - «PS4» и «XOne».
  2. Только две платформы показали рост в этот период - «PS4» и «XOne».
  3. Ранее, при вычислении периода среднего роста продаж мы считали период роста для различных платформ. Критерием попадание в такой список было появление признаков снижения тренда, который мы фиксировали с помощью скользящего среднего. Из списка топ-5 в него не попали лишь «PS4» и «XOne».
  4. Наибольший объем продаж в актуальном периоде с 2015 по 2016 приходиться «PS4». Следом идет «XOne».

Таким образом к перспективным платформам можно отнести только «PS4» и «XOne» и исключить остальные из сравнения.

In [49]:
# датасет для отобранных перспективных платформ в актуальный период
prospect_platforms_df = new_df.query('platform in @prospect_platforms')
prospect_platforms_df
Out[49]:
name platform year_of_release genre na_sales eu_sales jp_sales other_sales critic_score user_score rating total_sales
31 Call of Duty: Black Ops 3 PS4 2015 Shooter NaN NaN 0.36 NaN NaN NaN RP 0.36
77 FIFA 16 PS4 2015 Sports 1.12 NaN 0.06 NaN 82.0 4.3 E 1.18
87 Star Wars Battlefront (2015) PS4 2015 Shooter NaN NaN 0.22 NaN NaN NaN RP 0.22
94 FIFA 17 PS4 2016 Sports 0.66 NaN 0.08 NaN 85.0 5.0 E 0.74
99 Call of Duty: Black Ops 3 XOne 2015 Shooter NaN NaN 0.01 NaN NaN NaN RP 0.01
... ... ... ... ... ... ... ... ... ... ... ... ...
16630 Sébastien Loeb Rally Evo XOne 2016 Racing 0.00 0.01 0.00 0.0 63.0 8.2 E 0.01
16643 Rugby Challenge 3 XOne 2016 Sports 0.00 0.01 0.00 0.0 NaN 6.6 E 0.01
16645 ZombiU XOne 2016 Action 0.00 0.01 0.00 0.0 NaN NaN RP 0.01
16660 Prison Architect XOne 2016 Action 0.01 0.00 0.00 0.0 74.0 6.7 RP 0.01
16672 Metal Gear Solid V: The Definitive Experience XOne 2016 Action 0.01 0.00 0.00 0.0 NaN NaN M 0.01

468 rows × 12 columns

In [50]:
# график распределения продаж отдельных игр для перспективных платформ
fig = px.violin(prospect_platforms_df
                .pivot_table(index=prospect_platforms_df.index,
                             columns='platform',
                             values='total_sales',
                             aggfunc='sum'),
                color='platform',
                box=True,
                points='all',
                title='График распределения продаж отдельных игр <br>для перспективных платформ')
fig.update(layout_yaxis_range = [0,1])
fig.update_xaxes(title_text='Игровая платформа')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()

В топ-5 существующих платформ уже определились лидеры, так что графики строим только для платформ «PS4» и «XOne».
Медианные значения обеих платформ находятся приблизительно на одном уровне - у «XOne» он чуть более высокий. Также платформа «XOne» имеет больший межквартильного размах, а «PS4» большую концентрацию значений вокруг медианы.

Влияние отзывов пользователей и критиков на объем продаж¶

In [51]:
# оценка количества отсутствующих значений от общего размера датасета
prospect_platforms_df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 468 entries, 31 to 16672
Data columns (total 12 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   name             468 non-null    object 
 1   platform         468 non-null    object 
 2   year_of_release  468 non-null    int64  
 3   genre            468 non-null    object 
 4   na_sales         465 non-null    float64
 5   eu_sales         455 non-null    float64
 6   jp_sales         468 non-null    float64
 7   other_sales      458 non-null    float64
 8   critic_score     297 non-null    float64
 9   user_score       311 non-null    float64
 10  rating           468 non-null    object 
 11  total_sales      468 non-null    float64
dtypes: float64(7), int64(1), object(4)
memory usage: 47.5+ KB
In [52]:
# датасет для перспективных платформ с удаленными NaN
prospect_platforms_df_cutted = prospect_platforms_df.dropna(subset=['critic_score', 'user_score']).copy()
prospect_platforms_df_cutted
Out[52]:
name platform year_of_release genre na_sales eu_sales jp_sales other_sales critic_score user_score rating total_sales
77 FIFA 16 PS4 2015 Sports 1.12 NaN 0.06 NaN 82.0 4.3 E 1.18
94 FIFA 17 PS4 2016 Sports 0.66 NaN 0.08 NaN 85.0 5.0 E 0.74
105 Fallout 4 PS4 2015 Role-Playing 2.53 NaN 0.24 NaN 87.0 6.5 M 2.77
171 Uncharted 4: A Thief's End PS4 2016 Shooter 1.85 NaN 0.19 NaN 93.0 7.9 T 2.04
231 Uncharted: The Nathan Drake Collection PS4 2015 Action 2.07 1.71 0.08 NaN 86.0 8.1 T 3.86
... ... ... ... ... ... ... ... ... ... ... ... ...
16526 Dungeons 2 PS4 2016 Role-Playing 0.01 0.00 0.00 0.0 61.0 7.9 T 0.01
16530 Carmageddon: Max Damage PS4 2016 Action 0.01 0.00 0.00 0.0 51.0 5.5 M 0.01
16597 Saints Row: Gat out of Hell XOne 2015 Action 0.00 0.01 0.00 0.0 65.0 6.0 M 0.01
16630 Sébastien Loeb Rally Evo XOne 2016 Racing 0.00 0.01 0.00 0.0 63.0 8.2 E 0.01
16660 Prison Architect XOne 2016 Action 0.01 0.00 0.00 0.0 74.0 6.7 RP 0.01

290 rows × 12 columns

Для проведения анализа связей между продажами игр и их рейтингами, имеющиеся строки с NaN были удалены. Размер датасета уменьшился на треть, но это позволяет избежать искажений от усиления средних рейтингов.
Ранее мы посчитали платформу «PS4» более предпочтительной, потому анализ зависимости между рейтингами игр и объемами их продаж будем проводить для нее.

In [53]:
# срез для платформы PS4
query_ps4 = prospect_platforms_df_cutted.query('platform =="PS4"')

# расчет коэффициентов корреляции для платформы PS4
critic_score_corr = query_ps4['critic_score'].corr(query_ps4['total_sales'])
user_score_corr = query_ps4['user_score'].corr(query_ps4['total_sales'])
print('Корреляция между рейтингом критиков и продажами:', critic_score_corr,
      '\nКорреляция между рейтингом пользователей и продажами', user_score_corr)
Корреляция между рейтингом критиков и продажами: 0.4249884643634065 
Корреляция между рейтингом пользователей и продажами 0.02917016772517034
In [54]:
# диаграмма рассеяния оценок критиков для платформы PS4
fig = px.scatter(query_ps4, 
                 x='user_score', 
                 y='total_sales', 
                 title='Диаграмма зависимости между оценками критиков <br>и продажами для платформы «PS4»')
fig.update_xaxes(title_text='Оценки критиков, ед.')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()
In [55]:
# диаграмма рассеяния оценок пользователей для платформы PS4
fig = px.scatter(query_ps4, 
                 x='user_score', 
                 y='total_sales', 
                 title='Диаграмма зависимости между оценками пользователей <br>и продажами для платформы «PS4»')
fig.update_xaxes(title_text='Оценки пользователей, ед.')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()
In [56]:
# корреляция между рейтингами
fig = px.imshow(prospect_platforms_df_cutted.query('platform =="PS4"')[['critic_score', 'user_score', 'total_sales']]
                .corr().round(2),
                title='Корреляция между рейтингами <br>и продажами для платформы «PS4»',
                text_auto=True)
fig.update_xaxes(side="top")
fig.show()

Мы уже сделали выбор в пользу «PS4» и увидели как связаны отзывы с объемом продаж. Посмотрим, можно полученные для «PS4» параметры корреляции соотнести с другими платформами. А точнее, со второй перспективной платформой «XOne».

In [57]:
# корреляция рейтингов и продаж для платформы XOne
fig = px.imshow(prospect_platforms_df_cutted.query('platform =="XOne"')[['critic_score', 'user_score', 'total_sales']]
                .corr().round(2),
                title='Корреляция между рейтингами <br>и продажами для платформы «XOne»',
                text_auto=True)
fig.update_xaxes(side="top")
fig.show()
In [58]:
# корреляция рейтингов и продаж для всех актуальных платформ
(
    df.query('platform in @top5_platforms.index')
    .dropna(subset=['critic_score', 'user_score', 'total_sales'])
    .groupby('platform')[['critic_score', 'user_score', 'total_sales']]
    .corr()
)
Out[58]:
critic_score user_score total_sales
platform
3DS critic_score 1.000000 0.741440 0.367392
user_score 0.741440 1.000000 0.276057
total_sales 0.367392 0.276057 1.000000
PS3 critic_score 1.000000 0.631154 0.516953
user_score 0.631154 1.000000 0.308589
total_sales 0.516953 0.308589 1.000000
PS4 critic_score 1.000000 0.557654 0.409130
user_score 0.557654 1.000000 0.013981
total_sales 0.409130 0.013981 1.000000
WiiU critic_score 1.000000 0.770080 0.342312
user_score 0.770080 1.000000 0.362236
total_sales 0.342312 0.362236 1.000000
XOne critic_score 1.000000 0.472462 0.386290
user_score 0.472462 1.000000 -0.092953
total_sales 0.386290 -0.092953 1.000000

Анализируются данные за выделенный актуальный период в существовании платформы. На диаграммах рассеяния можно заметить, что некоторые игры - лидеры продаж, получившие высокую оценку критиков, у пользователей получают существенно более низкую оценку. И такое смещение - это общая тенденция. Связано это с тем, что пользователи вносят в оценку много субъективных факторов. Часто оценка выставляется, только чтобы излить негативные эмоции.
Бросается в глаза, что очень мало игр с низким, < 60% рейтингом. Такие, видимо, вообще нет смысла продавать.
В целом, рейтинг пользователей не влияет на объем продаж игры, а коэффициент корреляции близкий нулю (-0.03) это подтверждает. Для рейтинга критиков коэффициент корреляции 0.4 показывает среднюю положительную связь с продажами. Высокий рейтинг критиков способствует увеличению продаж, но сам по себе их не гарантирует.
Выводы по исследованию связи рейтинга и продаж для платформы «PS4» можно распространить и на другие платформы, поскольку рейтинг игры учитывает только особенности самой игры - он платформо-независим, а сами выводы были ожидаемы.

Сравнение объема продаж игр различных жанров¶

In [59]:
# актуальный период
actual_period = [2015, 2016]
# распределение игр по жанрам за 2015-2016 гг.
genres_total_actual = new_df.query('year_of_release in @actual_period').groupby('genre')['total_sales'].sum()
# диаграмма распределение игр по жанрам
fig = go.Figure(data=[go.Pie(labels=genres_total_actual.index, values=genres_total_actual.values, hole=.3)])
fig.update_layout(title='Распределение игр по жанрам <br>в общем объеме продаж для всех платформ за 2015-2016 гг.')
fig.show()
In [60]:
# сводная таблица по жанрам за 2015-2016 гг. для действующих платформ
(
    new_df.query('year_of_release in @actual_period')
    .groupby('genre')['total_sales']
    .agg(['sum', 'median', 'count']) 
    .sort_values(by='sum', ascending=False)
)
Out[60]:
sum median count
genre
Action 92.85 0.060 428
Shooter 66.65 0.360 81
Sports 45.21 0.120 107
Role-Playing 44.05 0.115 132
Misc 14.17 0.060 71
Fighting 12.37 0.090 37
Adventure 11.98 0.030 110
Racing 10.86 0.055 42
Platform 9.28 0.100 28
Simulation 6.15 0.100 33
Strategy 2.98 0.050 29
Puzzle 0.72 0.030 7
In [61]:
# выборка по годам для всех платформ в 2016-ом году
genres_total = new_df.query('year_of_release in @actual_period and platform == "PS4"').groupby('genre')['total_sales'].sum()
# диаграмма распределение игр по жанрам в общем объеме продаж в 2016-ом году
fig = go.Figure(data=[go.Pie(labels=genres_total.index, values=genres_total.values, hole=.3)])
fig.update_layout(title='Распределение игр по жанрам <br>в общем объеме продаж <br>для платформы «PS4» за 2015-2016 гг.')
fig.show()
In [62]:
# сводная таблица по жанрам за 2015-2016 гг. для действующих платформ
(
    new_df.query('year_of_release in @actual_period and platform == "PS4"')
    .groupby('genre')['total_sales']
    .agg(['sum', 'median', 'count']) 
    .sort_values(by='sum', ascending=False)
)
Out[62]:
sum median count
genre
Action 45.30 0.100 111
Shooter 26.92 0.360 31
Sports 19.72 0.300 31
Role-Playing 16.98 0.120 43
Fighting 7.57 0.165 16
Racing 5.76 0.130 14
Adventure 5.16 0.065 24
Platform 2.49 0.140 7
Misc 2.23 0.045 14
Simulation 1.23 0.210 6
Strategy 0.30 0.080 3
Puzzle 0.02 0.020 1

Для начала оценим какую долю рынка занимали отдельные жанровые категории за период с 2015 по 2016 годы. Здесь явно выделяются четыре жанра - Action, Shooter, Sports, Role-Playing.

Мы знаем, в этот период с серьезным отрывом лидировала платформа «PS4». Посмотрим какую долю рынка формировали продажи именно этой платформы.

In [63]:
# расчет суммарных продаж по платформам
sales2016 = new_df.query('year_of_release == 2016').groupby('platform')['total_sales'].sum()
sales2016
Out[63]:
platform
3DS      8.57
PC       5.25
PS3      3.60
PS4     54.18
PSV      4.25
Wii      0.18
WiiU     4.60
X360     1.52
XOne    24.10
Name: total_sales, dtype: float64
In [64]:
# доля рынка PS4
print('Доля продаж игр на платформе "PS4" в суммарных продажах для всех платформ в 2016 году: {:.1%}'
      .format(sales2016[3] / sales2016.sum()))
Доля продаж игр на платформе "PS4" в суммарных продажах для всех платформ в 2016 году: 51.0%

Так как доля платформы «PS4» на рынке составляет более половины, то стоит предположить, что именно она и формирует основные тенденции. Поэтому стоит взглянуть на динамику продаж топовых жанров только для этой платформы.

In [65]:
# основные игровые жанры
top_genres = ['Shooter', 'Action', 'Sports']
# диаграмма изменения продаж топовых жанров
fig = px.line(df.query('platform == "PS4" and year_of_release >= 2012 and genre in @top_genres')
             .pivot_table(index='year_of_release', columns='genre', values='total_sales', aggfunc='sum', fill_value=0),
             title='Динамика продаж основных игровых жанров <br>для платформы «PS4»')
fig.update_xaxes(title_text='Год выпуска',
                tickvals = [2012, 2013, 2014, 2015, 2016])
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()

Видно, что жанр Action сдал свои позиции к 2016 году. Теперь лидером является Shooter и продажи этого жанра растут. Однако, его лидерство никак не отображается на картине продаж в целом по платформам за период с 2015 по 2016 гг. - он все же немного уступает жанру Action.
Из этого можно заключить, что для дальнейшего анализа стоит использовать самые свежие данные за 2016 год. Посмотрим, как распределились объемы продаж отдельных жанров.

In [66]:
# выборка по годам для всех платформ в 2016-ом году
genres_total = new_df.query('year_of_release == 2016').groupby('genre')['total_sales'].sum()
# диаграмма распределение игр по жанрам в общем объеме продаж в 2016-ом году
fig = go.Figure(data=[go.Pie(labels=genres_total.index, values=genres_total.values, hole=.3)])
fig.update_layout(title='Распределение игр по жанрам <br>в общем объеме продаж <br>для всех платформ в 2016 году')
fig.show()
In [67]:
# сводная таблица по жанрам за 2016 г. для действующих платформ
(
    new_df.query('year_of_release == 2016')
    .groupby('genre')['total_sales']
    .agg(['sum', 'median', 'count']) 
    .sort_values(by='sum', ascending=False)
)
Out[67]:
sum median count
genre
Shooter 30.01 0.240 47
Action 28.78 0.050 178
Sports 14.58 0.120 48
Role-Playing 12.94 0.120 54
Fighting 4.47 0.085 16
Adventure 3.82 0.020 56
Platform 3.23 0.100 15
Racing 2.79 0.050 24
Misc 2.60 0.040 32
Simulation 1.89 0.025 18
Strategy 1.13 0.060 13
Puzzle 0.01 0.010 1

На оценку популярности игровых жанров влияют не только текущие предпочтения пользователей, по точность классификации игр по жанрам, даже сами жанры могут со временем меняться или исчезать. Поэтому будем рассматривать самую актуальную информацию. На диаграмме распределение игр по жанрам в общем объеме продаж в 2016 году видно на рынке компьютерных игр преобладает жанр Shooter, также велики доли игр жанров Action, Sports и Role-Playing.
Такая картина обусловлена технической мощью современных игровых платформ, а значит возможностью предложить разработчиками еще более захватывающие, насыщенные действием и качественной графикой играми. Это является надежной гарантией удержания пользовательского интереса к играм типа экшен и в будущем.
Хотелось бы обратить внимание на крайне низкую долю жанра Strategy. Игры этого жанра, предназначенные для персональных компьютеров весьма популярны, имеют широкий круг фанатов, вокруг них собственная субкультура (например, "Warcraft", переросший из стратегии реального времени в ролевой "World of Warcraft"). "Неприсобленность" стратегий для игровых приставок и их эволюция в более активные жанры лишний раз показывает специфическую нацеленность приставок на экшен-игры в широком смысле этого слова.

In [68]:
# выборка по годам для для платформы PS4 в 2016-ом году
genres_total = new_df.query('year_of_release == 2016 and platform == "PS4"').groupby('genre')['total_sales'].sum()
# диаграмма распределение игр по жанрам в общем объеме продаж в 2016-ом году
fig = go.Figure(data=[go.Pie(labels=genres_total.index, values=genres_total.values, hole=.3)])
fig.update_layout(title='Распределение игр по жанрам <br>в общем объеме продаж <br>для платформы «PS4» в 2016 году')
fig.show()
In [69]:
# сводная таблица по жанрам за 2016 г. для платформы PS4
(
    new_df.query('year_of_release == 2016 and platform == "PS4"')
    .groupby('genre')['total_sales']
    .agg(['sum', 'median', 'count']) 
    .sort_values(by='sum', ascending=False)
)
Out[69]:
sum median count
genre
Shooter 15.98 0.305 20
Action 14.85 0.060 59
Sports 7.72 0.315 16
Role-Playing 5.98 0.200 18
Fighting 2.74 0.150 7
Adventure 2.19 0.030 14
Platform 2.16 0.140 5
Racing 1.19 0.070 9
Misc 0.60 0.035 10
Simulation 0.55 0.060 4
Strategy 0.22 0.110 2

К 2016 году платформа «PS4» заняла больше половины рынка, так что распределение жанров для нее само по себе показательно, кроме того она была определена ранее как наиболее перспективная. Диаграмма для «PS4» почти не отличается от общей, что не удивительно. За несколько лет список наиболее популярных жанров не изменился. В топе - Action, Shooter, Sports, Role-Playing. Основное изменение в том, что жанр Shooter усилил свою позиции и вытеснил жанр Action с верхней строчки топа.
Обращает на себя внимание и то, что типичное медианное значения объема продаж игр жанра Shooter почти в 5 раз превышает значение для Action, который удерживает позиции только благодаря большому разнообразию игр. Но к 2016 году заметно как падение количества таких игр, так и их цена.

Выводы¶

В ходе анализа была исследована динамика объема продаж игр для различных платформ. Были определены характерный период жизни игровой платформы - 8 лет, период роста продаж - 4 года и актуальный период - 2 года. На основе сравнения актуальных платформ была выделена наиболее перспективная платформа - «PS4».
Также было проведено сравнение различных игровых жанров, исследованы влияющие на прибыльность факторы, и выбраны наиболее популярные - Shooter, Action, Sports, Role-Playing. При этом жанр Shooter кажется наиболее предпочтительным.

Портрет типичного пользователя¶

Задача¶

Составить портрет пользователя каждого региона.
Определить для пользователя каждого региона (NA, EU, JP):

  • Самые популярные платформы (топ-5);
  • Самые популярные жанры (топ-5);
  • Оценить, влияет ли рейтинг ESRB на продажи в отдельном регионе;

Сравнение наиболее популярных платформ для каждого региона¶

Для создания портрета типичного пользователя нам стоит захватить достаточно широкий круг данных. В качестве временного периода выберем актуальный период с 2015 по 2016 год.

In [70]:
# расчет суммарных продаж отдельных платформ по регионам
platform_region = (
    new_df.query('year_of_release in @actual_period').loc[:, ['platform', 'na_sales', 'eu_sales', 'jp_sales']]
    .groupby('platform').sum()
)
platform_region
Out[70]:
na_sales eu_sales jp_sales
platform
3DS 7.33 7.39 13.48
PC 3.72 9.10 0.00
PS3 5.66 7.30 4.97
PS4 54.84 48.28 12.05
PSV 0.54 1.08 8.41
Wii 0.49 0.73 0.00
WiiU 8.86 6.49 2.66
X360 8.05 4.21 0.00
XOne 45.71 21.82 0.18
In [71]:
# график объема продаж по платформам в зависимости от региона
fig = px.bar(platform_region, 
             barmode='group', 
             title='Объем продаж по игровым платформам <br>в зависимости от региона')
fig.update_xaxes(title_text='Платформы')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()
In [72]:
# топ-5 платформ по продажам в Северной Америке
platform_region['na_sales'].sort_values(ascending=False).head()
Out[72]:
platform
PS4     54.84
XOne    45.71
WiiU     8.86
X360     8.05
3DS      7.33
Name: na_sales, dtype: float64
In [73]:
# топ-5 платформ по продажам в Европе
platform_region['eu_sales'].sort_values(ascending=False).head()
Out[73]:
platform
PS4     48.28
XOne    21.82
PC       9.10
3DS      7.39
PS3      7.30
Name: eu_sales, dtype: float64
In [74]:
# Топ-5 платформ по продажам в Японии
platform_region['jp_sales'].sort_values(ascending=False).head()
Out[74]:
platform
3DS     13.48
PS4     12.05
PSV      8.41
PS3      4.97
WiiU     2.66
Name: jp_sales, dtype: float64

В Северной Америке и Европе в топ-5 вошли почти одни и те же платформы, вверху списка расположились «PS4»(PlayStation 4) и «XOne»(Xbox One). В Японии вверху топ-5 расположилась «3DS»(Nintendo 3DS), а «XOne» даже не попала в пятерку. На примере «XOne»(Xbox One) американской компании "Microsoft" видно, что региональные потребители отдают предпочтения местным компаниям - в Северной Америке «XOne» продается больше, чем где-либо еще. Европа следует в предпочтениях за США, вероятно из-за отсутствия игровых приставок собственного производства. Не вызывает удивления, что лидирующую позицию в целом заняла самая современная (на 2016 год) приставка «PS4»(PlayStation 4) от японской транснациональной корпорации "Sony", при этом с сильным отрывом от конкурентов. В Японии весь топ-5 заняли приставки японский компаний и вверху оказалась платформа «3DS»(Nintendo 3DS) от национальной японской компании «Nintendo».

Сравнение наиболее популярных жанров для каждого региона¶

In [75]:
# расчет суммарных продаж отдельных жанров по регионам
genre_region = (
    new_df.query('year_of_release in @actual_period').loc[:, ['genre', 'na_sales', 'eu_sales', 'jp_sales']]
    .groupby('genre').sum()
)
genre_region
Out[75]:
na_sales eu_sales jp_sales
genre
Action 33.68 32.83 16.52
Adventure 3.84 4.67 2.22
Fighting 5.54 3.72 1.54
Misc 5.58 4.26 3.19
Platform 3.78 3.20 1.42
Puzzle 0.06 0.13 0.52
Racing 2.82 6.52 0.29
Role-Playing 16.84 11.81 11.15
Shooter 34.57 22.17 2.33
Simulation 1.36 3.74 0.53
Sports 26.31 11.78 1.65
Strategy 0.82 1.57 0.39
In [76]:
# график объема продаж по жанрам в зависимости от региона
fig = px.bar(genre_region, 
             barmode='group', 
             title='Объем продаж по игровым жанрам <br>в зависимости от региона')
fig.update_xaxes(title_text='Жанры')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()
In [77]:
# топ-5 жанров по продажам в Северной Америке
genre_region['na_sales'].sort_values(ascending=False).head()
Out[77]:
genre
Shooter         34.57
Action          33.68
Sports          26.31
Role-Playing    16.84
Misc             5.58
Name: na_sales, dtype: float64
In [78]:
# топ-5 жанров по продажам в Европе
genre_region['eu_sales'].sort_values(ascending=False).head()
Out[78]:
genre
Action          32.83
Shooter         22.17
Role-Playing    11.81
Sports          11.78
Racing           6.52
Name: eu_sales, dtype: float64
In [79]:
# топ-5 жанров по продажам в Японии
genre_region['jp_sales'].sort_values(ascending=False).head()
Out[79]:
genre
Action          16.52
Role-Playing    11.15
Misc             3.19
Shooter          2.33
Adventure        2.22
Name: jp_sales, dtype: float64

Сразу бросается в глаза отличие японского топ-5 от двух других. В Японии такой популярный жанр как Shooter неожиданно оказался не вверху, внизу топ-5, его вытеснил жанр Role-Playing. Также в этом топе вместо жанра Sports появился жанр Adventure. Вероятно, связано это с общей мифологизацией образа мышления у японцев и желанием сбежать в фантазийный виртуальный мир от давления социума. Вообще, почти маниакальное увлечение молодыми японцами такого рода компьютерными играми хорошо видно по тому, какое количество японских аниме посвящено перерождению героя в фантазийном или компьютерном мире.
Для Северной Америки и Европы топ-5 отличается незначительно. Можно обратить внимание на жанр Sports, который в Северной Америки расположился строчкой ниже чем в Европе. Напрашивается очевидное объяснение - значительную часть этой категории занимают футбольные игры, а в США футбол не популярен. А жанр Shooter в Европе пока еще не достиг такой популярности, как в Северной Америке.

Влияние рейтинга ESRB на продажи в отдельном регионе¶

In [80]:
# расчет суммарных продаж по категориям ESRB по регионам
rating_region = (
    new_df.query('year_of_release in @actual_period').loc[:, ['rating', 'na_sales', 'eu_sales', 'jp_sales']].groupby('rating').sum()
)
rating_region
Out[80]:
na_sales eu_sales jp_sales
rating
E 26.59 18.79 3.85
E10+ 17.87 11.54 1.81
M 47.03 34.00 4.29
RP 20.85 24.25 24.10
T 22.86 17.82 7.70
In [81]:
# график объема продаж по категориям рейтинга ESRB в зависимости от региона
fig = px.bar(rating_region, 
             barmode='group', 
             title='Объем продаж по категориям рейтинга ESRB <br>в зависимости от региона')
fig.update_xaxes(title_text='Категории ESRB')
fig.update_yaxes(title_text='Объем продаж, млн. долл.')
fig.show()
In [82]:
# топ-5 категорий ESRB по продажам в Северной Америке
rating_region['na_sales'].sort_values(ascending=False).head()
Out[82]:
rating
M       47.03
E       26.59
T       22.86
RP      20.85
E10+    17.87
Name: na_sales, dtype: float64
In [83]:
# топ-5 категорий ESRB по продажам в Европе
rating_region['eu_sales'].sort_values(ascending=False).head()
Out[83]:
rating
M       34.00
RP      24.25
E       18.79
T       17.82
E10+    11.54
Name: eu_sales, dtype: float64
In [84]:
# топ-5 категорий ESRB по продажам в Японии
rating_region['jp_sales'].sort_values(ascending=False).head()
Out[84]:
rating
RP      24.10
T        7.70
M        4.29
E        3.85
E10+     1.81
Name: jp_sales, dtype: float64

В топ-5 во всех регионах вошли одни те же категории, описывающие универсального потребителя - взрослые и подростки, и не включающие в себя специфические категории «EC» («Для детей младшего возраста») или «AO» («Только для взрослых»). В Японии на первом месте оказалась «RP» («Рейтинг ожидается») — можно предположить, что за этим стоит категория «Для всех». Тогда некоторые отличия будут, ведь в Северной Америке и Европе первое место занимает категория «M»(«Для взрослых»). Но, скорее всего, — это не так.

Выводы¶

Целью исследование было составление портрета типичного пользователя для нескольких регионов мира - Северной Америки, Европы и Японии. В ходе исследования игровых предпочтений пользователей различных регионов мира выяснилось, что они тяготеют к игровым платформам местного производства. Но, в целом, лидирующую позицию занимает «PS4»(PlayStation 4) компании "Sony", особенно в Европе.
Жанровые предпочтения отличаются, причем особенно сильно в Японии. В Европе и США предпочтения пользователей схожи, можно лишь заметить, что в Европе больше поклонников жанра Sports. В Японии и Европе топ возглавил достаточно универсальный жанр Action. В Северной Америке с первой строчки его потеснилShooter. Изучение рейтинга ESRB ожидаемое показало, что основной целевой категорией пользователей являются взрослые. Заметим, однако, что категория рейтинга ESRB, присвоенная игре, больше говорит о содержании игры, а не от том, кто в нее играет.

Проверка гипотез¶

Задача¶

Проверить гипотезы:

  • Средние пользовательские рейтинги платформ «Xbox One» и «PC» одинаковые;
  • Средние пользовательские рейтинги жанров Action (англ. «действие», экшен-игры) и Sports (англ. «спортивные соревнования») разные.

Проверка гипотез по игровым платформам¶

Проверка утверждения, что средние пользовательские рейтинги платформ «Xbox One» и «PC» одинаковые:

  • $H_0$: Средние двух генеральных совокупностей пользовательских рейтингов платформ «Xbox One» и «PC» равны между собой.
  • $H_1$: Они отличаются.

Для теста берутся полные выборки данных за период с 2008 по 2016 год. Пороговое значение alpha устанавливается в $5\%$ для двустороннего теста.

In [85]:
# датасет для всех платформ с удаленными NaN
user_scores = new_df.dropna(subset=['user_score']).copy()
In [86]:
# кол-во строк в срезе по платформам
user_scores.query('platform == "XOne"')['user_score'].count(), user_scores.query('platform == "PC"')['user_score'].count()
Out[86]:
(121, 84)
In [87]:
# тест сравнения пользовательских рейтингов двух платформ по полным выборкам
xb1_sample = user_scores.query('platform == "XOne"')['user_score']
pc_sample = user_scores.query('platform == "PC"')['user_score']

alpha = 0.05
xb1_pc_result = st.ttest_ind(xb1_sample, pc_sample, equal_var=False)

print('p-value', xb1_pc_result.pvalue)
if xb1_pc_result.pvalue < alpha:
    print('Отвергаем нулевую гипотезу.')    
else:
    print('Не получилось отвергнуть нулевую гипотезу.')
p-value 0.2946308864003345
Не получилось отвергнуть нулевую гипотезу.

Проверка гипотез по пользовательским рейтингам¶

Проверка утверждения, что пользовательские рейтинги жанров Action (англ. «действие») и Sports (англ. «виды спорта») разные

  • $H_0$: Средние двух генеральных совокупностей пользовательских рейтингов жанров Action и Sports не больше и не меньше друг друга.
  • $H_1$: Они отличаются.

Для теста берутся полные выборки данных за период с 2008 по 2016 год. Пороговое значение alpha устанавливается в $5\%$ для одностороннего теста.

In [88]:
# кол-во строк в срезе по жанрам
user_scores.query('genre == "Action"')['user_score'].count(), user_scores.query('genre == "Sports"')['user_score'].count()
Out[88]:
(193, 82)
In [89]:
# тест сравнения пользовательских рейтингов двух жанров по полным выборкам
action_sample = user_scores.query('genre == "Action"')['user_score']
sports_sample = user_scores.query('genre == "Sports"')['user_score']

alpha = 0.05
action_sports_result = st.ttest_ind(action_sample, sports_sample, equal_var=False)

print('p-value', action_sports_result.pvalue)
if action_sports_result.pvalue / 2 < alpha:
    print('Отвергаем нулевую гипотезу.')    
else:
    print('Не получилось отвергнуть нулевую гипотезу.')
p-value 5.97163549920592e-10
Отвергаем нулевую гипотезу.

Выводы¶

В первом случае t-тест не смог опровергнуть гипотезу, что средние двух генеральных совокупностей пользовательских рейтингов платформ «Xbox One» и «PC» равны между собой. Во втором случае была принята альтернативная гипотеза о том, что средние двух генеральных совокупностей пользовательских рейтингов жанров Action и Sports отличаются.
Из результатов статистических тестов можно сделать вывод, что степень популярности игр среди пользователей не связана с популярностью платформы, но прямо зависит от ее жанра.

Общий вывод¶

Задание¶

Написать общий вывод.

Вывод по обработке данных:¶

Исходные данные не нуждались в значительной предварительной обработке. Не было выявлено дубликатов и аномалий. Некоторым столбцам требовалось сменить тип данных, был изменен регистр названий столбцов. В столбцах с рейтингами был заменен ряд значений. Также там обнаружились многочисленные пропуски и большинство было оставлено. Исследовательский анализ данных в основном строится на изучении графиков и пропуски в виде NaN-значений не мешают их построению. Важнейшие изменения в данных были связаны с добавлением столбца общих продаж и обрезанием выбросов в столбцах продаж.

Вывод по результатам анализа:¶

Исследование показало, что игры на платформе "PlayStation 4" от "Sony" являются наиболее перспективным выбором. Платформа к 2016 году занимает более половины всего рынка, а игровые хиты для нее показывают высокие объемы продаж.
При изучении динамики объема продаж на протяжении срока жизни игровой платформы был разработан критерий фиксация спада продаж, четко определена средняя длительность роста и выделен период актуальности платформы. Для игровой платформы "PlayStation 4" признаки начала снижения продаж обнаружены не были, более того, не достигнуто значение средней продолжительности периода роста. И это позволяет надеяться, что платформа будет популярна еще какое-то время. Был определен портрет типичного пользователя. В качестве целевой возрастной были определены взрослые люди и подростки. Наиболее популярными жанрами являются шутеры, игры в стиле экшен и спортивные игры. Причем первые характеризуется еще и наиболее высоким типичным значением продаж. Важным фактором успешной продажи конкретной игры является ее высокий рейтинг у профессиональных критиков - между ним и объемом продаж обнаружена прямая зависимость. Однако, высокий рейтинг высоких продаж сам по себе не гарантирует. На него влияют другие факторы. Не исключено, что лучше продаются продолжения уже хорошо зарекомендовавших себя игр. Были проведены статистические тесты и проверены гипотезы о пользовательских предпочтениях в отношении жанров и игровых платформ. Ожидаемо выяснилось, что для пользователей скорее важен жанр игры, чем конкретная игровая платформа.